package org.common.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Currency;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.util.StringUtils;



/**
 * 这是soul的fromat工具类,处理所有跟各类数据格式间的转换
 * 
 * @author soul
 */
public class SF {
	private static final String PREFIX = "\\u";
	public static Pattern CHINESE_PATTERN = Pattern.compile("[\u4e00-\u9fa5]");
	public static Pattern NOT_ENGLISH_PATTERN = Pattern.compile("[\u0100-\ueeee]");
	public static final String anyStr="[\\s\\S]*?";//.*不能匹配换行符, .*是贪婪匹配, .*?是最小匹配
	public static final String pointStr="[.]";
	public static void main(String[] args) {
		System.out.println(isNum("8.5"));
	}
	/**
	 * native2ascii
	 * 
	 * @param text
	 * @return
	 */
	public static String native2ascii(String text) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < text.length(); i++) {
			char ch = text.charAt(i);
			String ascii = native2ascii(ch);
			sb.append(ascii);
		}
		return sb.toString();
	}

	/**
	 * char -> ascii
	 * 
	 * @param ch
	 * @return
	 */
	private static String native2asciiCode(char ch) {
		return Integer.toHexString(ch);
	}

	/**
	 * 数字格式化, 保留两位小数
	 * 
	 * @param db
	 * @return
	 */
	public static String fn(double db) {
		DecimalFormat d = new DecimalFormat();
		d.setMinimumFractionDigits(2);
		d.setMaximumFractionDigits(2);
		return d.format(db);
	}
	
	/**
	 * 获取本地货币符
	 * 
	 * @return
	 * @author soul
	 * @since 2013-6-26
	 */
	public static String getCurrencySymbol() {
		return Currency.getInstance(Locale.getDefault()).getSymbol();
	}

	/**
	 * 替换xml中的空元素
	 * @param xml
	 * @return
	 */
	public static String removeEmptyElements(String xml){
		return xml.replaceAll("\\s*<\\w+/>\\s*", "");
	}
	
	
	public static int countCnStr(String str,String rp){
		if(str!=null){
			return str.replaceAll("[\u4e00-\u9fa5]",rp ).length();
		}
		return 0;
	}
	
	public static List<String> query(String str, String pattern, int groupIndex) {
		List<String> list = new ArrayList<>();
		Matcher m = Pattern.compile(pattern).matcher(str);
		while (m.find()) {
			list.add(m.group(groupIndex));
		}
		return list;
	}
	public static<K,V> void each(List<K> keys,List<V> vals,BiConsumer<K,V> bf){
		for(int i=0,len=keys.size();i<len;i++){
			bf.accept(keys.get(i), vals.get(i));
		}
	}
	public static<K> void each(K[] objs,Consumer<K> cs){
		for(int i=0,len=objs.length;i<len;i++){
			cs.accept(objs[i]);
		}
	}

	public static List<String[]> queryArray(String str, String pattern, int... groupIndexs) {
		List<String[]> list = new ArrayList<>();
		Matcher m = Pattern.compile(pattern).matcher(str);
		int len = groupIndexs.length;
		while (m.find()) {
			String[] data = new String[len];
			for (int i = 0; i < len; i++) {
				data[i] = m.group(groupIndexs[i]);
			}
			list.add(data);
		}
		return list;
	}
	public static List<Object> queryObject(String str, String pattern,BiFunction<Integer,String,Object> bf){
		List<Object> list = new ArrayList<>();
		Matcher m = Pattern.compile(pattern).matcher(str);
		while (m.find()) {
			Map<String, String> data = new HashMap<>();
			for (int i = 0,len=m.groupCount(); i < len; i++) {
				list.add(bf.apply(i, m.group(i)));
			}
			list.add(data);
		}
		return list;
	}
	public static List<Map<String, String>> queryMap(String str, String pattern, String[] names) {
		List<Map<String, String>> list = new ArrayList<>();
		//str=str.replaceAll("[\\s]+", " ");
		Matcher m = Pattern.compile(pattern).matcher(str);
		int len = names.length;
		while (m.find()) {
			Map<String, String> data = new HashMap<>();
			for (int i = 0; i < len; i++) {
				if (names[i] != null) {
					data.put(names[i], m.group(i));
				}
			}
			list.add(data);
		}
		return list;
	}
	public static List<Map<String, String>> queryMap(String str, String ... strs) {
		int slen=strs.length;
		if(slen%2!=0){
			throw new RuntimeException("匹配项个数必须是偶数");
		}
		int len=slen/2;
		String[] names=new String[len];
		StringBuilder patternStr=new StringBuilder();
		for(int i=0;i<slen;i++){
			if(i%2==0){
				names[i/2]=strs[i];
			}else{
				patternStr.append(anyStr).append(strs[i]);
			}
		}
		List<Map<String, String>> list = new ArrayList<>();
		Matcher m = Pattern.compile(patternStr.toString()).matcher(str);
		while (m.find()) {
			Map<String, String> data = new HashMap<>();
			for (int i = 0; i < len; i++) {
				data.put(names[i], m.group(i+1));
			}
			list.add(data);
		}
		return list;
	}
	
	
	/**
	 * 是否包含中文文字（不包括中文字符）
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isChinese(String str) {
		return CHINESE_PATTERN.matcher(str).find();
	}

	/**
	 * 是否包含特殊字符
	 * 
	 * @param str
	 * @return
	 */
	public static boolean notEnglish(String str) {
		return NOT_ENGLISH_PATTERN.matcher(str).find();
	}

	/**
	 * GBK 中文占2个,unicode占4个
	 * 
	 * @param str
	 * @param len
	 * @param charset
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String subBytes(String str, int len, String charset) throws UnsupportedEncodingException {
		// 测试编码
		// GBK中文占两个,子母1个
		// UNICODE 4或2个,子母2个
		// UTF-8 中文3,英文占1个
		// UTF-16 4或2个,子母2个
		// System.out.println(str.getBytes(charset).length+">>>"+new
		// String(Arrays.copyOfRange(str.getBytes(charset), 0, len),charset));
		byte[] bs = str.getBytes(charset);
		String rs = subBytes(bs, len, charset);
		if (rs.equals(str.substring(0, rs.length()))) {
			return rs;
		}
		return str.substring(0, rs.length() - 1);
	}

	/**
	 * GBK 中文占2个,unicode占3个
	 * 
	 * @param bs
	 * @param len
	 * @param charset
	 *            字符编码
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String subBytes(byte[] bs, int len, String charset) throws UnsupportedEncodingException {
		byte[] sbs = Arrays.copyOfRange(bs, 0, len);
		try {
			return new String(sbs, charset);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * char -> ascii
	 * 
	 * @param ch
	 * @return
	 */
	private static String native2ascii(char ch) {
		if (ch < 256) {
			return Character.toString(ch);
		}
		String hex = Integer.toHexString(ch);
		if (hex.length() < 4) {
			hex = "0" + hex;
		}
		return PREFIX + hex;
	}

	public static String toJsArray(String ss[]) {
		return new Object() {
			public String toJsArray(String ss[]) {
				if (ss == null) {
					return "[]";
				}
				StringBuilder sb = new StringBuilder("[");
				for (String s : ss) {
					sb.append("'");
					sb.append(s);
					sb.append("'");
					sb.append(",");
				}
				return sb.deleteCharAt(sb.lastIndexOf(",")).append("]").toString();
			}
		}.toJsArray(ss);
	}

	/**
	 * native2ascii
	 * 
	 * @param ascii
	 * @return
	 */
	public static String ascii2native(String text) {
		StringBuilder sb = new StringBuilder();
		int start = 0;
		int idx = text.indexOf(PREFIX);
		while (idx != -1) {
			// 上一个 Unicode 码与当前 Unicode 码之间的有效字符
			// eg: \u0101ABC\u0102 之间的ABC
			sb.append(text.substring(start, idx));
			// 转换当前 Unicode 码
			String ascii = text.substring(idx + 2, idx + 6);
			char ch = (char) Integer.parseInt(ascii, 16);
			sb.append(ch);
			// 查找下一个 Unicode
			start = idx + 6;
			idx = text.indexOf(PREFIX, start);
		}
		// 结尾的有效字符
		sb.append(text.substring(start));
		return sb.toString();
	}

	/**
	 * 将对象装换为字符串
	 * 
	 * @param obj
	 * @return
	 */
	public static String fs(Object obj) {
		if (obj == null) {
			return "";
		} else {
			return obj.toString();
		}
	}

	/**
	 * 将前面带零的数字字符串去前面的零
	 * 
	 * @param b
	 * @return
	 */
	public static String fb(String b) {
		if (b != null && !"".equals(b)) {
			// 如果字段是指数形式,则展开
			return new BigDecimal(b).toPlainString();
		} else {
			return "";
		}
	}

	/**
	 * 判断字符串是否有值,建议使用原方法
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isValue(String value) {
		System.out.println("|" + value + "|");
		return StringUtils.hasText(value);
	}

	/**
	 * 判断字符串是否有值
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isEmpty(String value) {
		return !StringUtils.hasText(value);
	}

	/**
	 * 判断字符串是否是整型(包括int,long,short)
	 * 
	 * @param value要判断的字符串
	 * @return
	 */
	public static boolean isIntValue(String value) {
		return value != null && value.matches("\\d+");
	}

	public static boolean isNum(String value) {
		return value != null && value.matches("\\d+(\\.\\d+)?");
	}

	public static boolean isBigDecimal(String value) {
		try {
			BigDecimal bd = new BigDecimal(value);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 将整数转化为一定长度的String
	 * 
	 * @param i
	 * @param length
	 * @return
	 */
	public static String formatInt(int i, int length) {
		return String.format("%0" + length + "d", i);
	}

	/**
	 *
	 * @param str
	 *            需要过滤的字符串
	 * @return
	 * @Description:过滤数字以外的字符
	 */
	public static String filterUnNumber(String str) {
		// 只允数字
		String regEx = "[^0-9]";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(str);
		// 替换与模式匹配的所有字符（即非数字的字符将被""替换）
		return m.replaceAll("").trim();
	}

	/**
	 * 将数字转化为String
	 * 
	 * @param b
	 * @return
	 */
	public static String fb(BigDecimal b) {
		if (b != null) {
			// 如果字段是指数形式,则展开
			return b.toPlainString();
		} else {
			return "";
		}
	}

	/**
	 * 将数字按刻度四舍五入后转化为String
	 * 
	 * @param b
	 * @param scale
	 * @return
	 */
	public static String fb(BigDecimal b, int scale) {
		if (b != null) {
			// 如果字段是指数形式,则展开
			return fb(b.setScale(scale, BigDecimal.ROUND_HALF_UP));
		} else {
			return "";
		}
	}

	/**
	 * 将数字按刻度,舍入模式,舍入后转化为String
	 * 
	 * @param b
	 *            数字
	 * @param scale
	 *            刻度
	 * @param roundingMode
	 *            舍入模式
	 * @return
	 */
	public static String fb(BigDecimal b, int scale, int roundingMode) {
		if (b != null) {
			// 如果字段是指数形式,则展开
			return fb(b.setScale(scale, roundingMode));
		} else {
			return "";
		}
	}

	/**
	 * 
	 */

	/**
	 * 将字符串装换为BigDecimal
	 * 
	 * @param n
	 * @return
	 */
	public static BigDecimal tb(String num) {
		if (num == null || "".equals(num)) {
			System.out.println("BigDecimal Errors>>>>>>>>>>>>>>[" + num + "]");
			return new BigDecimal("0");
		} else {
			if (!num.matches("[0-9]{1,30}") && !num.matches("[0-9]{1,30}.[0-9]{1,30}")) {
				if (!num.matches("-[0-9]{1,30}") && !num.matches("-[0-9]{1,30}.[0-9]{1,30}")) {
					System.out.println("BigDecimal Errors>>>>>>>>>>>>>>|" + num + "|");
				}
			}
			return new BigDecimal(num);
		}
	}

	/**
	 * 将日期转化为String
	 * 
	 * @param date
	 * @return
	 */
	public static String fd(Date date) {
		java.text.DateFormat dfm = new java.text.SimpleDateFormat("yyyy-MM-dd");
		if (date != null) {
			return dfm.format(date);
		} else {
			return "";
		}
	}

	/**
	 * 将日期转化为String
	 * 
	 * @param date
	 * @return
	 */
	public static String fd(Date date, String dm) {
		java.text.DateFormat dfm = new java.text.SimpleDateFormat(dm);
		if (date != null) {
			return dfm.format(date);
		} else {
			return "";
		}
	}

	/**
	 * 将日期转化为String
	 * 
	 * @param date
	 * @return
	 */
	public static String fdt(Date date) {
		return fdt(date, "yyyy-MM-dd hh:mm:ss");
	}

	/**
	 * 将日期转化为对应格式的String
	 * 
	 * @param date
	 * @return
	 */
	public static String fdt(Date date, String format) {
		java.text.DateFormat dfm = new java.text.SimpleDateFormat(format);
		if (date != null) {
			return dfm.format(date);
		} else {
			return "";
		}
	}

	/**
	 * 将日期转化为String
	 * 
	 * @param date
	 * @return
	 */
	public static String fd0(Date date) {
		java.text.DateFormat dfm = new java.text.SimpleDateFormat("yyyy.MM.dd");
		if (date != null) {
			return dfm.format(date);
		} else {
			return "";
		}
	}

	/**
	 * 将String 装化为标准的String
	 * 
	 * @param date
	 * @return
	 */
	public static String fd(String date) {
		return fd(td(date));
	}

	/**
	 * 日期格式化
	 * 
	 * @param date
	 * @return
	 */
	public static String fd(String date, String fm) {
		return fd(td(date), fm);
	}

	/**
	 * 将时间转化为String
	 * 
	 * @param date
	 * @return
	 */
	public static String ft(Date date) {
		java.text.DateFormat dfm = new java.text.SimpleDateFormat("HHmmss");
		if (date != null) {
			return dfm.format(date);
		} else {
			return "";
		}
	}

	/**
	 * 将字符串转化为日期的date
	 * 
	 * @param date
	 * @return
	 */
	public static Date td(String date) {
		String fm = "";
		Date d = null;
		if (date == null || "".equalsIgnoreCase(date)) {
			d = new Date();
		} else if (date.matches("[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}.*")) {
			// System.out.println("yyyy-MM-dd");
			fm = "yyyy-MM-dd";
		} else if (date.matches("[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}.*")) {
			// System.out.println("yyyy/MM/dd");
			fm = "yyyy/MM/dd";
		} else if (date.matches("[0-9]{4}.[0-9]{1,2}.[0-9]{1,2}.*")) {
			// System.out.println("yyyy.MM.dd");
			// .号可以匹配任意字符所以要放在最后
			fm = "yyyy.MM.dd";
		} else if (date.matches("[0-9]{8}.*")) {
			// System.out.println("yyyyMMdd");
			fm = "yyyyMMdd";
		} else {
			System.out.println("未辨识的日期格式:>>>" + date);
		}
		try {
			if (fm.equalsIgnoreCase("")) {
				d = new java.text.SimpleDateFormat("yyyyMMdd").parse("00000000");
			} else {
				d = new java.text.SimpleDateFormat(fm).parse(date);
			}
		} catch (Exception e) {
			e.getStackTrace();
		}
		return d;
	}

	/**
	 * 将字符串转化为日期的date
	 * 
	 * @param date
	 * @return
	 */
	public static Date td(String date, String fm) {
		Date d = null;
		try {
			d = new java.text.SimpleDateFormat(fm).parse(date);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return d;
	}

	/**
	 * 判断日期是否是工作日(周一到周五)
	 * 
	 * @param date
	 * @return
	 */
	public static boolean isWeekday(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int num = c.get(Calendar.DAY_OF_WEEK);
		if (num == 1 || num == 7) {
			return false;
		}
		return true;
	}

	/**
	 * 判断日期是否是工作日(周一到周五)
	 * 
	 * @param date
	 * @return
	 */
	public static boolean isWeekday(String dateString) {
		Date date = td(dateString);
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int num = c.get(Calendar.DAY_OF_WEEK);
		if (num == 1 || num == 7) {
			return false;
		}
		return true;
	}

	/**
	 * 判断日期是否是工作日(周一到周五)
	 * 
	 * @param date
	 * @return
	 */
	public static boolean isWeekday(String dateString, String fm) {
		Date date = td(dateString, fm);
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int num = c.get(Calendar.DAY_OF_WEEK);
		if (num == 1 || num == 7) {
			return false;
		}
		return true;
	}

	/**
	 * 数字字符串按位格式化,最大是18位
	 * 
	 * @param num
	 * @param length
	 * @return
	 */
	public static String zero(String num, int length) {
		if (num == null) {
			return num;
		}
		if (num.matches("[0-9]{1,18}")) {
			long l = new Long(num);
			num = String.format("%0" + length + "d", l);
		}
		return num;
	}

	/**
	 * 字符串按位格式化,补足在后面补足空格
	 * 
	 * @param num
	 * @param length
	 * @return
	 */
	public static String blank(String str, int length) {
		int len = length - str.length();
		if (len > 0) {
			return String.format("%s%" + len + "s", str, "");
		} else {
			return str;
		}

	}

	/**
	 * 模糊查询
	 * 
	 * @param pk
	 * @return
	 */
	public static String ls(String pk) {
		if (!isValue(pk)) {
			return "'%'";
		}
		return new StringBuffer("'%").append(pk).append("%'").toString();

	}

	public static String replacePrefix(String old, String pre, String sign) {
		int index = old.lastIndexOf(sign);
		if (index == -1) {
			return new StringBuffer(pre).append(sign).append(old).toString();
		}
		String suf = old.substring(index);
		return new StringBuffer(pre).append(suf).toString();
	}

	public static String replaceSuffix(String old, String suf, String sign) {
		int index = old.lastIndexOf(sign);
		if (index == -1) {
			return new StringBuffer(old).append(sign).append(suf).toString();
		}
		String pre = old.substring(0, old.lastIndexOf(sign));
		return new StringBuffer(pre).append(sign).append(suf).toString();
	}

	public static String sufString(String old, String sign) {
		int index = old.lastIndexOf(sign);
		if (index == -1) {
			return old;
		}
		return old.substring(index + sign.length());

	}

	public static String preString(String old, String sign) {
		int index = old.indexOf(sign);
		if (index == -1) {
			return old;
		}
		return old.substring(0, index);
	}

	@SuppressWarnings("unchecked")
	public static <T> T clone(T obj) {
		Class<? extends Object> cl = obj.getClass();
		Method met = null;
		try {
			met = cl.getMethod("clone");
		} catch (SecurityException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (NoSuchMethodException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if (met != null) {
			try {
				return (T) met.invoke(obj);
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return obj;
	}

	public static <K, V> Map<K, V> newMap(K[] ks, V[] vs) {
		Map<K, V> map = new HashMap<K, V>();

		return map;
	}

	/**
	 * 字符串格式补足,正数在后面补足,负数在后边补足
	 * 
	 * @param str
	 * @param size
	 * @param c
	 * @return
	 */
	public static String fs(String str, int size, char c) {

		return null;
	}

	/**
	 * 获取当前时间的上个月份,格式为yyyyMM
	 * 
	 * @return
	 */
	public static String getPreMonth() {
		Calendar c = Calendar.getInstance();
		c.set(Calendar.MONTH, c.get(Calendar.MONTH) - 1);
		return String.format("%04d%02d", c.get(Calendar.YEAR), c.get(Calendar.MONTH));

	}

	public static String getCode(String str) {
		String[] codes = { "GBK", "UTF-8", "UNICODE", "GB2312", "UTF-16", "ISO8859-1", "ASCII" };
		try {
			for (String code : codes) {
				if (str.equals(new String(str.getBytes(code)))) {
					return code;
				}
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 根据格式获取将包含键值对的字符串,加载到ProPerties中,
	 * 
	 * @param paramString
	 *            包含键值对的字符串,如&key1=value1&key2=value2
	 * @param paramPt
	 *            键值对格式,需过滤分割符
	 * @return ProPerties对象
	 */
	public static Properties loadParamString(String paramString, String paramPt) {
		Properties prop = new Properties();
		Matcher m = Pattern.compile(paramPt).matcher(paramString);
		while (m.find()) {
			prop.setProperty(m.group(1), m.group(2));
		}
		return prop;
	}

	public static String getCollectionSql(Collection<String> coll) {
		return new StringBuilder("(").append(StringUtils.collectionToDelimitedString(coll, ",", "'", "'")).append(")")
				.toString();
	}

	public static String join(Collection<String> coll) {
		return StringUtils.collectionToDelimitedString(coll, ",", "", "");
	}
	public static<T> List<T> toList(Iterable<T> it) {
		List<T> ss=new ArrayList<>();
		for(T obj:it){
			ss.add(obj);
		}
		return ss;
	}
	public static<T> List<T> toList(Stream<T> s){
		return s.collect(Collectors.toList());
	}
	/**
	 * 根据格式获取将包含键值对的字符串,加载到ProPerties中,这里假设键值对格式是"key=value",分割符是","
	 * 
	 * @param paramString
	 *            包含键值对的字符串,如&key1=value1&key2=value2
	 * @return ProPerties对象
	 */
	public static Properties loadParamString(String paramString) {
		return loadParamString(paramString, "([^=,]+)[=]([^,]+)");
	}

	/**
	 * 根据格式获取将包含键值对的字符串,加载到ProPerties中,这里假设分割符是是单个字符,键值对格式是"key=value",
	 * 
	 * @param paramString
	 *            包含键值对的字符串,如&key1=value1&key2=value2
	 * @return ProPerties对象
	 */
	public static Properties loadParamString(String paramString, char splitChar) {

		return loadParamString(paramString, new StringBuilder("([^=").append(splitChar).append("]+)[=]([^")
				.append(splitChar).append("]+)").toString());
	}

	public static String formatWord(String s0) {
		if ("".equals(s0)) {
			return "";
		}
		return s0.substring(0, 1).toUpperCase() + s0.substring(1);
	}

	public static String code2code(String strIn, String sourceCode, String targetCode) {
		String strOut = null;
		try {
			byte[] b = strIn.getBytes(sourceCode);
			for (int i = 0; i < b.length; i++) {
				System.out.print(b[i] + "  ");
			}
			strOut = new String(b, targetCode);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return strOut;
	}

	public static int countGroup(Pattern p) {
		return StringUtils.countOccurrencesOf(p.toString(), "(");
	}

	public static int countMatcher(Matcher m) {
		int flag = 0;
		m.pattern();
		// m.find();
		int start = -1;
		try {
			start = m.start();
			m.reset();
		} catch (Exception e) {
			// e.printStackTrace();
		}
		while (m.find()) {
			flag++;
		}
		if (start == -1) {
			m.reset();
		} else {
			m.find(start);
		}
		return flag;
	}

	public static void wrapMatcher(Matcher m) {
		int start = -1;
		try {
			start = m.start();
		} catch (Exception e) {
			// e.printStackTrace();
		}
		while (m.find()) {
			System.out.println(m.group());
		}
		if (start != -1) {
			int index = start;
			m.reset();
			while (index <= start && m.find(index)) {
				System.out.println(m.group());
				index = m.end();

			}
		}
	}

	/**
	 * String format的日期格式化方法
	 * 
	 * @param fm
	 *            默认为%tY-%tm-%td %tH:%tM:%tS
	 * @param dt
	 * @return
	 * @author soul
	 * @company dihua
	 * @since 2013-5-16
	 */
	public static String formatDate(String fm, Date dt) {
		// a|A 星期描述
		if (fm == null) {
			fm = "%tY-%tm-%td %tH:%tM:%tS";
		}
		Matcher mt = Pattern.compile("%t\\p{Alpha}").matcher(fm);
		int count = 0;
		while (mt.find()) {
			count++;
		}
		Object[] dts = new Date[count];
		Arrays.fill(dts, new Date());
		return String.format(fm, dts);
	}

	/**
	 * url解码
	 * 
	 * @param url
	 * @return
	 */
	public static String decode(String url) {
		try {
			return URLDecoder.decode(url, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "";
	}

	public static void debugCharset(String str) {
		for (String cs : new String[] { "unicode", "utf-8", "gbk", }) {

		}
	}

	public static String uuid() {

		UUID u = UUID.randomUUID();
		return u.toString().replace("-", "");
	}

	public static String uncap_first(String str) {
		return str.substring(0, 1).toLowerCase() + str.substring(1);
	}

	public static String cap_first(String str) {
		return str.substring(0, 1).toUpperCase() + str.substring(1);
	}

	/**
	 * 根据首字母比较字符串
	 * 
	 * @return
	 */
	public static Comparator<String> getStringComparator() {
		// TODO Auto-generated method stub
		return new Comparator<String>() {
			public int compare(String ti, String ta) {
				if (ti == null) {
					return -1;
				}
				if (ta == null) {
					return 1;
				}
				int til = ti.length();
				int tal = ta.length();
				if (til > tal) {
					int dd = ti.substring(0, tal - 1).compareTo(ta);
					return dd != 0 ? dd : til - tal;
				} else if (til < tal) {
					int dd = ti.compareTo(ta.substring(0, til - 1));
					return dd != 0 ? dd : til - tal;
				} else {
					return ti.compareTo(ta);
				}
			}
		};
	}

	/**
	 * 正则表达式替换
	 * 
	 * @param str
	 * @param regEx
	 * @param nS
	 * @return
	 */
	public static String replaceWithRegEx(String str, String regEx, String nS) {
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(str);
		return m.replaceAll(nS).trim();
	}

	/**
	 * 按默认规则获取字段的表字段名称 rptName-->rpt_name
	 * 
	 * @param field
	 * @return
	 */
	public static String getColumn(String field) {
		StringBuilder sb = new StringBuilder();
		for (char c : field.toCharArray()) {
			if (Character.isUpperCase(c)) {
				sb.append('_');
				sb.append(Character.toLowerCase(c));
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}

	public static String upCaseFirst(String field) {
		return Character.toUpperCase(field.charAt(0)) + field.substring(1);
	}

	/**
	 * 求模(数可以兼用负数)
	 * 
	 * @param num
	 * @param power
	 * @return
	 */
	public static int mod(int num, int power) {
		return Math.floorMod(num, power);
	}

	/**
	 * 数字转化为char类型
	 * 
	 * @param num
	 * @return
	 */
	public static char num2char(int num) {
		if (num >= 0 && num < 10) {
			return (char) (num + 48);
		}
		throw new IllegalArgumentException("此方法只处理0-9的数字");

	}

	public static boolean checkId(String id) throws IllegalArgumentException {
		if (id != null) {
			if (id.matches("\\d{17}[0-9X]{1}")) {
				int[] wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
				int sw = 0;
				for (int i = 0, len = wi.length; i < len; i++) {
					sw += wi[i] * Character.getNumericValue(id.charAt(i));
				}
				char[] checkNums = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' };
				return id.charAt(17) == checkNums[sw % 11];
			} else {
				throw new IllegalArgumentException("the format of id is wrong!");
			}

		} else {
			throw new IllegalArgumentException("id cannot be null!");
		}
	}

	/**
	 * 根据验证法则推算一位身份证号
	 * 
	 * @param id
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static String getId(String id) throws IllegalArgumentException {
		if (id != null) {
			if (id.matches("[0-9?]{17}[0-9X?]{1}") && id.matches("[^?]*[?]{1}[^?]*")) {
				int[] wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
				char[] checkNums = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' };
				char oldChar = '?';
				char newChar = '?';
				int index = id.indexOf(oldChar);
				if (index == 17) {
					int sw = 0;
					for (int i = 0, len = wi.length; i < len; i++) {
						sw += wi[i] * Character.getNumericValue(id.charAt(i));
					}
					newChar = checkNums[sw % 11];
				} else {
					int sw = 0;
					for (int i = 0, len = wi.length; i < len; i++) {
						if (i != index) {
							sw += wi[i] * Character.getNumericValue(id.charAt(i));
						}
					}
					int mod = Arrays.binarySearch(checkNums, id.charAt(17));
					int n = wi[index];
					// TODO (sw+n*?)%11=mod
					for (int i = 0; i < 10; i++) {
						if ((sw + n * i) % 11 == mod) {
							newChar = num2char(i);
							break;
						}
					}
				}
				return id.replace(oldChar, newChar);
			} else {
				throw new IllegalArgumentException("the format of id is wrong!");
			}

		} else {
			throw new IllegalArgumentException("id cannot be null!");
		}
	}
	/**
	 * 全部替换
	 * @param matcherStr 被替换的字符串
	 * @param patternStr 正则表达式
	 * @param f 操作方法
	 * @return
	 */
	public static String replaceAll(String matcherStr,String patternStr,Function<Matcher,String> f){
		// 生成Pattern对象与Matcher对象
				Pattern p = Pattern.compile(patternStr);
				Matcher m = p.matcher(matcherStr);
				// 创建目标字符串缓冲区
				StringBuffer sb = new StringBuffer();
				// 开始匹配检测
				while (m.find()){
					m.appendReplacement(sb,f.apply(m));
				}
				// 将最后一次替换后剩余的字符串添加进目标字符串缓冲区
				m.appendTail(sb);
				return sb.toString();
	}
	/**
	 * 使用lambda表达式搜索数据
	 * 
	 * @param ts
	 * @param prdc
	 * @return
	 */
	public static <T> ArrayList<T> query(Collection<T> ts, Predicate<T> prdc) {
		ArrayList<T> rs = new ArrayList<T>();
		Iterator<T> itrt = ts.iterator();
		while (itrt.hasNext()) {
			T t = itrt.next();
			if (prdc.test(t)) {
				rs.add(t);
			}
		}
		return rs;
	}
	/**
	 * 获取第一个有效字符串
	 * @param strs
	 * @return
	 */
	public static String firstString(String ...strs){
		String str=null;
		for(int i=0,len=strs.length;i<len;i++){
			str=strs[i];
			if(isValue(str)){
				break;
			}
		}
		return str;
	}
	
	
}
